package me.landery.modules.sinco.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qiniu.util.Json;
import lombok.RequiredArgsConstructor;
import me.landery.exception.EntityExistException;
import me.landery.modules.sinco.domain.Call;
import me.landery.modules.sinco.domain.Order;
import me.landery.modules.sinco.repository.CallRepository;
import me.landery.modules.sinco.repository.OrderRepository;
import me.landery.modules.sinco.service.CallService;
import me.landery.modules.sinco.service.OrderService;
import me.landery.modules.sinco.service.dto.CallDto;
import me.landery.modules.sinco.service.dto.CallQueryCriteria;
import me.landery.modules.sinco.service.dto.OrderQueryCriteria;
import me.landery.modules.sinco.service.mapstruct.CallMapper;
import me.landery.modules.sinco.service.mapstruct.OrderMapper;
import me.landery.modules.system.domain.Role;
import me.landery.modules.system.service.UserService;
import me.landery.modules.system.service.dto.RoleDto;
import me.landery.modules.system.service.dto.RoleSmallDto;
import me.landery.modules.system.service.dto.UserDto;
import me.landery.utils.*;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.time.chrono.MinguoDate;
import java.util.*;

/**
 * @Author cc.w
 * @Date 2022/6/7 16:55
 * @Version 1.0
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "call")
public class CallServiceImpl implements CallService {

    private final CallRepository callRepository;
    private final CallMapper callMapper;
    private final RedisUtils redisUtils;

    private final UserService userService;

    @Override
    public Map<String, Object> queryAll(CallQueryCriteria criteria, Pageable pageable) {
        Page<Call> page = callRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(callMapper::toDto).getContent(),page.getTotalElements());
    }

    @Override
    @Cacheable(key = "'id:' + #p0")
    @Transactional(rollbackFor = Exception.class)
    public CallDto findById(long id) {
        Call call = callRepository.findById(id).orElseGet(Call::new);
        ValidationUtil.isNull(call.getId(), "Call", "id", id);
        return callMapper.toDto(call);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(Call resources) {
        callRepository.save(resources);
    }

    @Override
    public List<CallDto> findByUsersId(Long id) {
        return callMapper.toDto(new ArrayList<>(callRepository.findByUserId(id)));
    }

    @Override
    public Call save(Call call1) {
        return callRepository.save(call1);
    }

    @Override
    public JSONObject queryCurrentDayTotal(Date date, String appId) {
        UserDto user = userService.findByName(SecurityUtils.getCurrentUsername());
        List<Map<String,Object>> alist = callRepository.queryCurrentDayTotal(user.getId(),date,appId);
        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        Set<Integer> hoursSet = new HashSet<>();
        long successCount = 0L;
        long failCount = 0L;
        for(Map<String,Object> t:alist){
            Integer i = Integer.parseInt(String.valueOf(t.get("hours")));
            BigInteger num = (BigInteger) t.get("num");
            Integer isSuccess = (Integer) t.get("success");
            if (isSuccess == 1){
                successCount += num.longValue();
            }else{
                failCount += num.longValue();
            }
            hoursSet.add(i);
        }

        JSONObject dayList = new JSONObject();
        dayList.put("hours",null);
        dayList.put("successCount",successCount);
        dayList.put("failCount",failCount);
        SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
        dayList.put("date_time", format1.format(date));
        if (failCount > 0){
            dayList.put("rate",String.format("%.2f", successCount*100.0/(successCount+failCount))+"%");
        }
        else{
            dayList.put("rate",String.format("%.2f", 100.00)+"%");
        }
        jsonObject.put("dayList",dayList);

        for(int i = 0; i<=23 ;i++){ //对于二十四个小时
            JSONObject tmp;
            tmp = new JSONObject();
            tmp.put("hours",String.valueOf(i));
            if (hoursSet.contains(i)){
                for(Map<String,Object> t:alist){
                    int t1 = Integer.parseInt(String.valueOf(t.get("hours")));
                    if(t1 == i){
                        Integer isSuccess = (Integer) t.get("success");
                        BigInteger num = (BigInteger) t.get("num");
                        if (isSuccess == 1){
                            tmp.put("successCount",num.longValue());

                        }else {
                            tmp.put("failCount", num.longValue());
                        }
                    }
                }

            }

            //没有值得赋0
            if (!tmp.containsKey("successCount")){
                tmp.put("successCount",0L);
            }
            if (!tmp.containsKey("failCount")){
                tmp.put("failCount",0L);
            }
            jsonArray.add(tmp);
        }
        jsonObject.put("dayOfHoursList",jsonArray);
        return jsonObject;
    }

    @Override
    public JSONObject queryHis10DayTotal(Date date, String appId) {
        UserDto user = userService.findByName(SecurityUtils.getCurrentUsername());
        List<Map<String,Object>> alist = callRepository.queryHis10DayTotal(user.getId(),date,appId);
        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        Set<String> dateSet = new HashSet<>();
        long successCount;
        long failCount;
        for(Map<String,Object> t:alist){
            String date_time = (String) t.get("date_time");
            dateSet.add(date_time);
        }

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -9);
        Date startDate = calendar.getTime();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, 1);
        Date endDate = calendar.getTime();

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        for(Date i = startDate; i.before(endDate);){
            JSONObject tmp;
            tmp = new JSONObject();
            String i_date_str = simpleDateFormat.format(i);
            tmp.put("date_time",i_date_str);
            if (dateSet.contains(simpleDateFormat.format(i))){
                for(Map<String,Object> t:alist){
                    String date_time = (String) t.get("date_time");
                    BigInteger num = (BigInteger) t.get("num");
                    Integer isSuccess = (Integer) t.get("success");
                    if (i_date_str.equals(date_time)){
                        if (isSuccess == 1){
                            tmp.put("successCount",num.longValue());
                        }else {
                            tmp.put("failCount", num.longValue());
                        }
                    }
                }
            }
            //没有值得赋0
            if (!tmp.containsKey("successCount")){
                tmp.put("successCount",0L);
            }
            if (!tmp.containsKey("failCount")){
                tmp.put("failCount",0L);
            }
            successCount = (long) tmp.get("successCount");
            failCount = (long) tmp.get("failCount");

            if (failCount > 0){
                tmp.put("rate",String.format("%.2f", successCount*100.0/(successCount+failCount))+"%");
            }
            else{
                tmp.put("rate",String.format("%.2f", 100.00)+"%");
            }
            jsonArray.add(tmp);
            //更新时间，往前加1
            calendar.setTime(i);
            calendar.add(Calendar.DATE, 1);
            i = calendar.getTime();
        }

        jsonObject.put("dayOf10HisList",jsonArray);
        return jsonObject;
    }

    @Override
    public JSONObject findRecordGk(){
        JSONObject jsonObject = new JSONObject();
        UserDto user = userService.findByName(SecurityUtils.getCurrentUsername());
        //查询今日调用成功率
        List<Map<String, Object>> alist = callRepository.queryCurrentDayRecordGk(user.getId(), new Date());
        long curentTotal;
        long currentFailureNum = 0L;
        long currentSuccessNum = 0L;
        for (Map<String,Object> t:alist){
            BigInteger num = (BigInteger) t.get("num");
            Integer isSuccess = (Integer) t.get("success");
            if (isSuccess == 1){
                currentSuccessNum += num.longValue();
            }else {
                currentFailureNum += num.longValue();
            }
        }
        curentTotal = currentFailureNum+ currentSuccessNum;
        jsonObject.put("curentTotal",curentTotal);
        jsonObject.put("currentSuccessNum",currentSuccessNum);
        jsonObject.put("currentFailureNum",currentFailureNum);
        //查询累计调用成功率

        List<Map<String, Object>> alist2 = callRepository.queryAllRecordGk(user.getId());

        long total;
        long failureNum = 0L;
        long successNum = 0L;
        for (Map<String,Object> t: alist2){
            BigInteger num = (BigInteger) t.get("num");
            Integer isSuccess = (Integer) t.get("success");
            if (isSuccess == 1){
                successNum += num.longValue();
            }else {
                failureNum += num.longValue();
            }
        }
        total = successNum+failureNum;
        jsonObject.put("total",total);
        jsonObject.put("failureNum",failureNum);
        jsonObject.put("successNum",successNum);
        return jsonObject;
    }

    @Override
    public JSONObject getCallTypePercent(Date date, String appId){
        JSONObject jsonObject = new JSONObject();
        UserDto user = userService.findByName(SecurityUtils.getCurrentUsername());
        //获取今日 调用分类占比
        List<Map<String, Object>> alist = callRepository.getCurrentToDayCallTypePercent(user.getId(),date,appId);
        JSONArray jsonArray = new JSONArray();
        for (Map<String,Object> t:alist){
            String ctype = (String) t.get("c_type");
            BigInteger num = (BigInteger) t.get("num");
            JSONObject jsonObject1 = new JSONObject();
            jsonObject1.put("name",ctype);
            jsonObject1.put("value",num.longValue());
            jsonArray.add(jsonObject1);
        }

        jsonObject.put("todayCallTypeData",jsonArray);

        //获取全部 调用分类占比

        List<Map<String, Object>> alist2 = callRepository.getAllCallTypePercent(user.getId(),appId);
        JSONArray jsonArray2 = new JSONArray();
        for (Map<String,Object> t:alist2){
            String ctype = (String) t.get("c_type");
            BigInteger num = (BigInteger) t.get("num");
            JSONObject jsonObject1 = new JSONObject();
            jsonObject1.put("name",ctype);
            jsonObject1.put("value",num.longValue());
            jsonArray2.add(jsonObject1);
        }
        jsonObject.put("allCallTypeData",jsonArray2);

        return jsonObject;

    }

}
